package com.by.common.redis.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisZSetCommands;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis工具类
 */
@Component
public class RedisUtils {
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    RedisTemplate<String, Object> redisTemplate;


    /**
     * 保存字符串
     *
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    /**
     * 字符串取值
     *
     * @param key
     * @return
     */
    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * 保存对象类型字符串
     *
     * @param key
     * @param value
     * @param <T>
     */
    public <T> void set(String key, T value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 对象类型字符串取值
     *
     * @param key
     * @param <T>
     * @return
     */
    public <T> T getObject(String key) {
        return (T) redisTemplate.opsForValue().get(key);
    }

    /**
     * 保存字符串并设定有效时间 单位为秒
     *
     * @param key
     * @param value
     * @param time
     */
    public void setex(String key, String value, long time) {
        stringRedisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 保存对象类型字符串，并设定有效时间 单位为秒
     *
     * @param key
     * @param value
     * @param time
     */
    public <T> void setex(String key, T value, long time) {
        redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 如果key不存在 设置成功
     *
     * @param key
     * @param value
     * @return
     */
    public <T> Boolean setnx(String key, T value) {
        return redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    /**
     * 如果key不存在 设置成功
     *
     * @param key
     * @param value
     * @return
     */
    public Boolean setnx(String key, String value) {
        return stringRedisTemplate.opsForValue().setIfAbsent(key, value);
    }

    /**
     * 在key对应的值后面追加 value ,如果key不存在，
     * 先创建一个空的key再追加
     *
     * @param key
     * @param value
     */
    public int append(String key, String value) {
        return stringRedisTemplate.opsForValue().append(key, value);
    }

    /**
     * 获取从start到end之间的字符串值
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public String getrange(String key, long start, long end) {
        return stringRedisTemplate.opsForValue().get(key, start, end);
    }

    /**
     * 给指定key设定值，并返回旧值
     *
     * @param key
     * @param value
     * @return
     */
    public String getset(String key, String value) {
        return stringRedisTemplate.opsForValue().getAndSet(key, value);
    }

    /**
     * 给指定key设定值，并返回旧值
     *
     * @param key
     * @param value
     * @return
     */
    public <T> T getset(String key, T value) {
        return (T) redisTemplate.opsForValue().getAndSet(key, value);
    }

    /**
     * 使key对应的值自增，如果不存在，则先创建
     *
     * @param key
     * @return
     */
    public long incr(String key) {
        return stringRedisTemplate.opsForValue().increment(key);
    }

    /**
     * 使key对应的值增加指定delta长度
     *
     * @param key
     * @param delta
     * @return
     */
    public long incrby(String key, long delta) {
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 使key对应的值增加指定delta长度
     *
     * @param key
     * @param delta
     * @return
     */
    public double incrbyfloat(String key, double delta) {
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 使key对应的值自减
     *
     * @param key
     * @return
     */
    public long decrby(String key) {
        return stringRedisTemplate.opsForValue().decrement(key);
    }

    /**
     * 使key对应的值减去指定delta长度
     *
     * @param key
     * @return
     */
    public long decrby(String key, long delta) {
        return stringRedisTemplate.opsForValue().decrement(key, delta);
    }

    /**
     * 同时设定多个值
     *
     * @param map
     */
    public void mset(Map map) {
        stringRedisTemplate.opsForValue().multiSet(map);
    }

    /**
     * 同时取多个值
     *
     * @param keys
     * @return
     */
    public List mget(Collection<String> keys) {
        return stringRedisTemplate.opsForValue().multiGet(keys);
    }

    /**
     * 同时设定多个值，如果key对应的值不存在，不做处理
     *
     * @param map
     * @return
     */
    public Boolean msetnx(Map map) {
        return stringRedisTemplate.opsForValue().multiSetIfAbsent(map);
    }

    /**
     * 获取指定字符串长度
     *
     * @param key
     * @return
     */
    public long strlen(String key) {
        return stringRedisTemplate.opsForValue().size(key);
    }

    /**
     * 存储hash
     *
     * @param key
     * @param hashKey
     * @param value
     * @param <T>
     * @param <M>
     */
    public <T, M> void hset(String key, T hashKey, M value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    /**
     * 读取对应key中对应的hashKey值
     *
     * @param key
     * @param hashKey
     * @param <T>
     * @param <M>
     * @return
     */
    public <T, M> T hget(String key, M hashKey) {
        return (T) redisTemplate.opsForHash().get(key, hashKey);
    }

    /**
     * 读取key对应的多个hashKeys值
     *
     * @param key
     * @param hashKeys
     * @return
     */
    public List<Object> hmget(String key, Collection<Object> hashKeys) {
        return redisTemplate.opsForHash().multiGet(key, hashKeys);
    }

    /**
     * 遍历hash集合
     *
     * @param key
     * @param options
     * @return
     */
    public Cursor<Map.Entry<Object, Object>> hscan(String key, ScanOptions options) {
        return redisTemplate.opsForHash().scan(key, options);
    }

    /**
     * 如果key对应的hashKey值存在，保存值，否则不做操作
     *
     * @param key
     * @param hashKey
     * @param value
     * @param <K>
     * @param <M>
     * @return
     */
    public <K, M> Boolean hsetnx(String key, K hashKey, M value) {
        return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
    }

    /**
     * 返回指定
     * key的hashKsy
     * 对应值的字符串长度
     *
     * @param key
     * @param hashKsy
     * @param <T>
     * @return
     */
    public <T> long hstrlen(String key, T hashKsy) {
        return redisTemplate.opsForHash().lengthOfValue(key, hashKsy);
    }

    /**
     * 返回指定key中所有的hashkey
     *
     * @param keys
     * @return
     */
    public Set<Object> hkeys(String keys) {
        return redisTemplate.opsForHash().keys(keys);
    }

    /**
     * 返回指定key中所有的hashvalue
     *
     * @param keys
     * @return
     */
    public List<Object> hvals(String keys) {
        return redisTemplate.opsForHash().values(keys);
    }

    /**
     * 返回指定key对应的所有hash对
     *
     * @param key
     * @return
     */
    public Map<Object, Object> hgetall(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 返回指定key中k-v的数量
     *
     * @param key
     * @return
     */
    public long hlen(String key) {
        return stringRedisTemplate.opsForHash().size(key);
    }

    /**
     * 删除指定key的field值
     *
     * @param key
     * @param hashKeys
     * @param <T>
     * @return
     */
    public <T> long hdel(String key, T hashKeys) {
        return redisTemplate.opsForHash().delete(key, hashKeys);
    }

    /**
     * 给指定key的hashKey值以delta增加值，如果hashKey不存在先创建初始为0再加
     *
     * @param key
     * @param hashKey
     * @param delta
     * @param <T>
     * @return
     */
    public <T> long hincrby(String key, T hashKey, long delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    /**
     * 给指定key的hashKey值以delta增加值，如果hashKey不存在先创建初始为0再加
     *
     * @param key
     * @param hashKey
     * @param delta
     * @param <T>
     * @return
     */
    public <T> double hincrbyfloat(String key, T hashKey, double delta) {
        return redisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    /**
     * 向指定的key 从左入栈（向队列的头部增加数据）
     *
     * @param key
     * @param value
     * @param <T>
     * @return
     */
    public <T> long lpush(String key, T value) {
        return redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * 从指定key的左边移除并返回第一个值 （从队列头部移除并返回值）
     *
     * @param key
     * @return
     */
    public Object lpop(String key) {
        return redisTemplate.opsForList().leftPop(key);
    }

    /**
     * 向指定的key从右入栈(向队列的末尾增加数据)
     *
     * @param key
     * @param value
     * @param <T>
     * @return
     */
    public <T> long rpush(String key, T value) {
        return redisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * 从指定key的右边移除并返回第一个值 (从队列末尾移除并返回值)
     *
     * @param key
     * @return
     */
    public Object rpop(String key) {
        return redisTemplate.opsForList().rightPop(key);
    }

    /**
     * 向指定key的列表的指定值从左插入一个数据
     *
     * @param key
     * @param pivot
     * @param value
     * @param <T>
     * @param <M>
     * @return
     */
    public <T, M> Object linsert(String key, T pivot, M value) {
        return redisTemplate.opsForList().leftPush(key, pivot, value);
    }

    /**
     * 从列表头开始 返回指定key对应索引位置的值
     *
     * @param key
     * @param index
     * @return
     */
    public Object lindex(String key, long index) {
        return redisTemplate.opsForList().index(key, index);
    }

    /**
     * 返回指定key列表的长度
     *
     * @param key
     * @return
     */
    public long llen(String key) {
        return redisTemplate.opsForList().size(key);
    }

    /**
     * 当key存在时，向列表头部插入值，否则不操作
     *
     * @param key
     * @param value
     * @param <T>
     * @return
     */
    public <T> long lpushx(String key, T value) {
        return redisTemplate.opsForList().leftPushIfPresent(key, value);
    }

    /**
     * 从指定key的列表移除count个相同的元素
     *
     * @param key
     * @param count
     * @param value
     * @param <T>
     * @return
     */
    public <T> long lrem(String key, long count, T value) {
        return redisTemplate.opsForList().remove(key, count, value);
    }

    /**
     * 设置指定key指定索引位置的值（相当于是修改）
     *
     * @param key
     * @param index
     * @param value
     * @param <T>
     */
    public <T> void lset(String key, long index, T value) {
        redisTemplate.opsForList().set(key, index, value);
    }

    /**
     * 从指定列表的移除尾部的值并将其加入目录列表
     *
     * @param sourceKey
     * @param destinationKey
     * @return
     */
    public Object rpoplpush(String sourceKey, String destinationKey) {
        return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey, destinationKey);
    }

    /**
     * 当key存在时，向列表尾部插入值，否则不操作
     *
     * @param key
     * @param value
     * @param <T>
     * @return
     */
    public <T> long rpushx(String key, T value) {
        return redisTemplate.opsForList().rightPushIfPresent(key, value);
    }

    /**
     * 指定过期时间后删除key中最左的一个值 单位为秒
     *
     * @param key
     * @param timeout
     * @return
     */
    public Object blpop(String key, long timeout) {
        return redisTemplate.opsForList().leftPop(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 指定过期时间后删除key中最右的一个值 单位为秒
     *
     * @param key
     * @param timeout
     * @return
     */
    public Object brpop(String key, long timeout) {
        return redisTemplate.opsForList().rightPop(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 指定过期时间后，移除sourceKey中最右的值，并将移除的值插入destinationKey中最左侧
     *
     * @param sourceKey
     * @param destinationKey
     * @param timeout
     * @return
     */
    public Object brpoplpush(String sourceKey, String destinationKey, long timeout) {
        return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey, destinationKey, timeout, TimeUnit.SECONDS);
    }

    /**
     * 添加一个元素到指定的集合中
     *
     * @param key
     * @param value
     * @param <T>
     */
    public <T> void sadd(String key, T value) {
        redisTemplate.opsForSet().add(key, value);
    }

    /**
     * 查看指定key 对应的所有集合元素
     *
     * @param key
     * @return
     */
    public Set<String> smembers(String key) {
        return stringRedisTemplate.opsForSet().members(key);
    }

    /**
     * 返回集合中的数量
     *
     * @param key
     * @return
     */
    public long scard(String key) {
        return stringRedisTemplate.opsForSet().size(key);
    }

    /**
     * 返回集合中的差集
     *
     * @param key
     * @param otherKey
     * @return
     */
    public Set<String> sdiff(String key, String otherKey) {
        return stringRedisTemplate.opsForSet().difference(key, otherKey);
    }

    /**
     * 返回集合中的差集
     *
     * @param keys
     * @return
     */
    public Set<String> sdiff(Collection<String> keys) {
        return stringRedisTemplate.opsForSet().difference(keys);
    }

    /**
     * 返回集合中的差集
     *
     * @param key
     * @return
     */
    public Set<String> sdiff(String key, Collection<String> otherkeys) {
        return stringRedisTemplate.opsForSet().difference(key, otherkeys);
    }

    /**
     * 取出指定key的差集 存入目标集合中
     *
     * @param keys
     * @param destKey
     * @return
     */
    public long sdiffstore(Collection<String> keys, String destKey) {
        return stringRedisTemplate.opsForSet().differenceAndStore(keys, destKey);
    }

    /**
     * 取出指定key的差集 存入目标集合中
     *
     * @param destKey
     * @return
     */
    public long sdiffstore(String key, String otherKey, String destKey) {
        return stringRedisTemplate.opsForSet().differenceAndStore(key, otherKey, destKey);
    }

    /**
     * 取出指定key的差集 存入目标集合中
     *
     * @param destKey
     * @return
     */
    public long sdiffstore(String key, Collection<String> keys, String destKey) {
        return stringRedisTemplate.opsForSet().differenceAndStore(key, keys, destKey);
    }

    /**
     * 返回多个集合的交集
     *
     * @param key
     * @param otherKey
     * @return
     */
    public Set<String> sinter(String key, String otherKey) {
        return stringRedisTemplate.opsForSet().intersect(key, otherKey);
    }

    /**
     * 返回多个集合的交集
     *
     * @return
     */
    public Set<String> sinter(Collection<String> keys) {
        return stringRedisTemplate.opsForSet().intersect(keys);
    }

    /**
     * 返回多个集合的交集
     *
     * @return
     */
    public Set<String> sinter(String key, Collection<String> otherkeys) {
        return stringRedisTemplate.opsForSet().intersect(key, otherkeys);
    }

    /**
     * 获取多个集合的交集存储到目标集合中
     *
     * @param keys
     * @param destKay
     * @return
     */
    public long sinterstore(Collection<String> keys, String destKay) {
        return stringRedisTemplate.opsForSet().intersectAndStore(keys, destKay);
    }

    /**
     * 获取多个集合的交集存储到目标集合中
     *
     * @param destKay
     * @return
     */
    public long sinterstore(String key, Collection<String> otherKeys, String destKay) {
        return stringRedisTemplate.opsForSet().intersectAndStore(key, otherKeys, destKay);
    }

    /**
     * 获取多个集合的交集存储到目标集合中
     *
     * @param destKay
     * @return
     */
    public long sinterstore(String key, String otherKey, String destKay) {
        return stringRedisTemplate.opsForSet().intersectAndStore(key, otherKey, destKay);
    }

    /**
     * 判断指定的key对应的集合中是否有给定的值
     *
     * @param key
     * @param o
     * @param <T>
     * @return
     */
    public <T> Boolean sismember(String key, T o) {
        return stringRedisTemplate.opsForSet().isMember(key, o);
    }

    /**
     * 从源集合中移除指定元素到目标集合，如果目标集合中存在该元素则只从源集合移除
     *
     * @param key
     * @param value
     * @param destKey
     * @return
     */
    public Boolean smove(String key, String value, String destKey) {
        return stringRedisTemplate.opsForSet().move(key, value, destKey);
    }

    /**
     * 移除返回 一个或
     * 多个随机元素
     *
     * @param key
     * @return
     */
    public String spop(String key) {
        return stringRedisTemplate.opsForSet().pop(key);
    }

    /**
     * 移除返回 一个或
     * 多个随机元素
     *
     * @param key
     * @return
     */
    public List<String> spop(String key, long count) {
        return stringRedisTemplate.opsForSet().pop(key, count);
    }

    /**
     * 返回 一个或多个随机元素
     *
     * @param key
     * @return
     */
    public String srandmember(String key) {
        return stringRedisTemplate.opsForSet().randomMember(key);
    }

    /**
     * 返回 一个或多个随机元素
     *
     * @param key
     * @param count
     * @return
     */
    public List<String> srandmember(String key, long count) {
        return stringRedisTemplate.opsForSet().randomMembers(key, count);
    }

    /**
     * 删除给定集合中的元素
     *
     * @param key
     * @param value
     * @param <T>
     * @return
     */
    public <T> long srem(String key, T value) {
        return stringRedisTemplate.opsForSet().remove(key, value);
    }

    /**
     * 获取所有键值对
     *
     * @param key
     * @param options
     * @return
     */
    public Cursor<String> sscan(String key, ScanOptions options) {
        return stringRedisTemplate.opsForSet().scan(key, options);
    }

    /**
     * 合并并返回集合中的所有成员 （不带重复的)
     *
     * @param keys
     * @return
     */
    public Set<String> sunion(Collection<String> keys) {
        return stringRedisTemplate.opsForSet().union(keys);
    }

    /**
     * 合并并返回集合中的所有成员 （不带重复的)
     *
     * @return
     */
    public Set<String> sunion(String key, String otherKey) {
        return stringRedisTemplate.opsForSet().union(key, otherKey);
    }

    /**
     * 合并并返回集合中的所有成员 （不带重复的)
     *
     * @return
     */
    public Set<String> sunion(String key, Collection<String> otherkeys) {
        return stringRedisTemplate.opsForSet().union(key, otherkeys);
    }

    /**
     * 合并集合中的所有成员并存储到目标集合中
     *
     * @param keys
     * @param destKey
     * @return
     */
    public long sunionstore(Collection<String> keys, String destKey) {
        return stringRedisTemplate.opsForSet().unionAndStore(keys, destKey);
    }

    /**
     * 合并集合中的所有成员并存储到目标集合中
     *
     * @param destKey
     * @return
     */
    public long sunionstore(String key, String otherKey, String destKey) {
        return stringRedisTemplate.opsForSet().unionAndStore(key, otherKey, destKey);
    }

    /**
     * 合并集合中的所有成员并存储到目标集合中
     *
     * @param destKey
     * @return
     */
    public long sunionstore(String key, Collection<String> otherKeys, String destKey) {
        return stringRedisTemplate.opsForSet().unionAndStore(key, otherKeys, destKey);
    }

    /**
     * 添加元素到集合中
     *
     * @param key
     * @param value
     * @param score
     * @return
     */
    public Boolean zadd(String key, String value, double score) {
        return stringRedisTemplate.opsForZSet().add(key, value, score);
    }

    /**
     * 向指定key中添加元素，按照score值由小到大进行排列
     * 集合中对应元素已存在，会被覆盖，包括score
     *
     * @param key
     * @param tuples
     * @return
     */
    public long zadd(String key, Set<ZSetOperations.TypedTuple<String>> tuples) {
        return stringRedisTemplate.opsForZSet().add(key, tuples);
    }

    /**
     * 返回有序集合中指定范围的元素,按分数从小到大排序
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> zrange(String key, long start, long end) {
        return stringRedisTemplate.opsForZSet().range(key, start, end);
    }

    /**
     * 返回有序集合中元素的个数
     *
     * @param key
     * @return
     */
    public long zcard(String key) {
        return stringRedisTemplate.opsForZSet().zCard(key);
    }

    /**
     * 返回有序集合中score的值在min和max之间的成员
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public long zcount(String key, double min, double max) {
        return stringRedisTemplate.opsForZSet().count(key, min, max);
    }

    /**
     * 为有序集key的成员member的score值加上增量
     *
     * @param key
     * @param value
     * @param delte
     * @return
     */
    public double zincrby(String key, String value, double delte) {
        return stringRedisTemplate.opsForZSet().incrementScore(key, value, delte);
    }

    /**
     * 计算交集，并且把结果放到destKey中
     *
     * @param key
     * @param otherKey
     * @param destKey
     * @return
     */
    public long zinterstore(String key, String otherKey, String destKey) {
        return stringRedisTemplate.opsForZSet().intersectAndStore(key, otherKey, destKey);
    }

    /**
     * 计算交集，并且把结果放到destKey中
     *
     * @param key
     * @param otherKeys
     * @param destKey
     * @return
     */
    public long zinterstore(String key, Collection<String> otherKeys, String destKey) {
        return stringRedisTemplate.opsForZSet().intersectAndStore(key, otherKeys, destKey);
    }

    /**
     * 计算并集，并且把结果放到destKey中
     *
     * @param key
     * @param otherkey
     * @param destKey
     * @return
     */
    public long zunionstore(String key, String otherkey, String destKey) {
        return stringRedisTemplate.opsForZSet().unionAndStore(key, otherkey, destKey);
    }

    /**
     * 计算并集，并且把结果放到destKey中
     *
     * @param key
     * @param otherkeys
     * @param destKey
     * @return
     */
    public long zunionstore(String key, Collection<String> otherkeys, String destKey) {
        return stringRedisTemplate.opsForZSet().unionAndStore(key, otherkeys, destKey);
    }

    /**
     * 根据分数范围有序集合中的元素
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Set<String> zrangebyscore(String key, double min, double max) {
        return stringRedisTemplate.opsForZSet().rangeByScore(key, min, max);
    }

    /**
     * 根据分数范围有序集合中的元素
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Set<String> zrangebyscore(String key, double min, double max, long offset, long count) {
        return stringRedisTemplate.opsForZSet().rangeByScore(key, min, max, offset, count);
    }

    /**
     * 返回集合中指定元素排行的位置 (从小到大）
     *
     * @param key
     * @param o
     * @param <T>
     * @return
     */
    public <T> long zrank(String key, T o) {
        return stringRedisTemplate.opsForZSet().rank(key, o);
    }

    /**
     * 删除有序集合中的元素
     *
     * @param key
     * @param value
     * @param <T>
     * @return
     */
    public <T> long zrem(String key, T value) {
        return stringRedisTemplate.opsForZSet().remove(key, value);
    }

    /**
     * 删除指定排行位置内的所有成员
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public long zremrangebyrank(String key, long start, long end) {
        return stringRedisTemplate.opsForZSet().removeRange(key, start, end);
    }

    /**
     * 删除指定分数范围内的所有成员
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public long zremrangebyscore(String key, double min, double max) {
        return stringRedisTemplate.opsForZSet().removeRangeByScore(key, min, max);
    }

    /**
     * 按分数从大小排序，返回指定区间内的成员
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> zrevrange(String key, long start, long end) {
        return stringRedisTemplate.opsForZSet().reverseRange(key, start, end);
    }

    /**
     * 返回有序集合中指定分数区间内的成员，分数由高到低排序
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Set<String> zrevrangebyscore(String key, double min, double max) {
        return stringRedisTemplate.opsForZSet().reverseRangeByScore(key, min, max);
    }

    /**
     * 返回有序集合中成员的排名(从大到小)
     *
     * @param key
     * @param o
     * @param <T>
     * @return
     */
    public <T> long zrevrank(String key, T o) {
        return stringRedisTemplate.opsForZSet().reverseRank(key, o);
    }

    /**
     * 迭代元素
     *
     * @param key
     * @param options
     * @return
     */
    public Cursor<ZSetOperations.TypedTuple<String>> zscan(String key, ScanOptions options) {
        return stringRedisTemplate.opsForZSet().scan(key, options);
    }

    /**
     * 返回指定成员的分数值
     *
     * @param key
     * @param o
     * @param <T>
     * @return
     */
    public <T> double zscore(String key, T o) {
        return stringRedisTemplate.opsForZSet().score(key, o);
    }

    /**
     * 返回分数最大的成员及分数
     */
    public ZSetOperations.TypedTuple<String> bzpopmax(String key) {
        return stringRedisTemplate.opsForZSet().popMax(key);
    }

    /**
     * 返回分数最大的成员及分数
     */
    public Set<ZSetOperations.TypedTuple<String>> bzpopmax(String key, long count) {
        return stringRedisTemplate.opsForZSet().popMax(key, count);
    }

    /**
     * 返回分数最小的成员及分数
     */
    public ZSetOperations.TypedTuple<String> bzpopmin(String key) {
        return stringRedisTemplate.opsForZSet().popMin(key);
    }

    /**
     * 返回分数最小的成员及分数
     */
    public Set<ZSetOperations.TypedTuple<String>> bzpopmin(String key, long count) {
        return stringRedisTemplate.opsForZSet().popMin(key, count);
    }

    /**
     * 获取字典排序的元素
     *
     * @param key
     * @param range
     * @return
     */
    public Set<Object> zrangebylex(String key, RedisZSetCommands.Range range) {
        return redisTemplate.opsForZSet().rangeByLex(key, range);
    }

    /**
     * 获取字典排序的元素
     *
     * @param key
     * @param range
     * @return
     */
    public Set<Object> zrangebylex(String key, RedisZSetCommands.Range range, RedisZSetCommands.Limit limit) {
        return redisTemplate.opsForZSet().rangeByLex(key, range, limit);
    }

    /**
     * 获取字典daoxu排序的元素
     *
     * @param key
     * @param range
     * @return
     */
    public Set<Object> zrevrangebylex(String key, RedisZSetCommands.Range range) {
        return redisTemplate.opsForZSet().reverseRangeByLex(key, range);
    }

    /**
     * 获取字典daoxu排序的元素
     *
     * @param key
     * @param range
     * @return
     */
    public Set<Object> zrevrangebylex(String key, RedisZSetCommands.Range range, RedisZSetCommands.Limit limit) {
        return redisTemplate.opsForZSet().reverseRangeByLex(key, range, limit);
    }

    /**
     * 按字典顺序删除元素
     *
     * @param key
     * @param range
     * @return
     */
    public long zremrangebylex(String key, RedisZSetCommands.Range range) {
        return stringRedisTemplate.opsForZSet().removeRangeByLex(key, range);
    }

}
